package com.hugehard.here;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.provider.ContactsContract;

import com.pinyin4android.PinyinUtil;

public class ContactsManager {

	private final static String TAG = ContactsManager.class.getSimpleName();
	
	private ArrayList<ContactItem> mAllContactItemList = new ArrayList<ContactItem>();
	private ArrayList<CallLogItem> mRecentContactItemList = new ArrayList<CallLogItem>();
	
	private ArrayList<ContactItem> mNormalContactItemList = new ArrayList<ContactItem>();
	private ArrayList<ContactItem> mAbnormalContactItemList = new ArrayList<ContactItem>();

	private static class SingletonClassInstance {
		private static final ContactsManager instance = new ContactsManager();
	}

	public static ContactsManager getInstance() {
		return SingletonClassInstance.instance;
	}
	
	final class ContactItem extends BaseContactItem implements Comparable<ContactItem> {
		public String mPinyin = "";
		
		public ContactItem(String phoneNumber, String contactName) {
			super(phoneNumber, contactName);
		}
		
		@Override
		public int compareTo(ContactItem another) {
			return mPinyin.compareTo(another.mPinyin);
		}
	}
	
	class BaseContactItem {
		public String mPhoneNumber = "";
		public String mContactName = "";
		public String mPinyin = "";
		public int mType = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
		
		public BaseContactItem(String phoneNumber, String contactName) {
			mPhoneNumber = phoneNumber;
			mContactName = contactName;
		}
	}
	
	final class CallLogItem extends BaseContactItem {		
		public CallLogItem(String phoneNumber, String contactName) {
			super(phoneNumber, contactName);
		}
	}
	
	
	/**
	 * load recent contacts from DataBase
	 * @param context
	 * @return boolean
	 */
	public boolean loadRecentContactsFromDB(Context context) {
		if (context == null) {
			return false;
		}
		HashSet<String> phoneNumberSet = new HashSet<String>();
		mRecentContactItemList.clear();
		String[] strFields = {
                android.provider.CallLog.Calls.NUMBER, 
                android.provider.CallLog.Calls.TYPE,
                android.provider.CallLog.Calls.CACHED_NAME,
                android.provider.CallLog.Calls.CACHED_NUMBER_TYPE
                };
        String strOrder = android.provider.CallLog.Calls.DATE + " DESC"; 
        Cursor mCallCursor = context.getContentResolver().query(
                android.provider.CallLog.Calls.CONTENT_URI,
                strFields,
                null,
                null,
                strOrder
                );
        while (mCallCursor.moveToNext()) {
        	String number = mCallCursor.getString(mCallCursor.getColumnIndex(strFields[0]));
        	String name = mCallCursor.getString(mCallCursor.getColumnIndex(strFields[2]));
        	int phoneType = mCallCursor.getInt(mCallCursor.getColumnIndex(strFields[1]));
        	if (name != null && name.equals("") == false) {
        		if (phoneNumberSet.contains(number) == false) {
        			phoneNumberSet.add(number);
        			CallLogItem callLogItem = new CallLogItem(number, name);
            		callLogItem.mType = phoneType;
            		mRecentContactItemList.add(callLogItem);
        		}
        	}
        }
        mCallCursor.close();
		return true;
	}
	
	
	/**
	 * get recent contacts
	 * @return ArrayList<CallLogItem>
	 */
	public final ArrayList<CallLogItem> getRecentContactItemList() {
		return mRecentContactItemList;
	}
	
	
	/**
	 * load all contacts from DataBase
	 * @param context
	 * @return boolean
	 */
	public boolean loadAllContactFromDB(Context context) {
		if (context == null) {
			return false;
		}
		HashSet<String> phoneNumberSet = new HashSet<String>();
		mAllContactItemList.clear();
		ContentResolver cr = context.getContentResolver();
		Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
				null, null, null);
		if (cur.getCount() > 0) {
			while (cur.moveToNext()) {
				String id = cur.getString(cur
						.getColumnIndex(BaseColumns._ID));
				String name = cur
						.getString(cur
								.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
				if (Integer
						.parseInt(cur.getString(cur
								.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
					Cursor pCur = cr.query(
							ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
							null,
							ContactsContract.CommonDataKinds.Phone.CONTACT_ID
									+ " = ?", new String[] { id }, null);
					while (pCur.moveToNext()) {
						String phoneNo = pCur
								.getString(pCur
										.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
						
						if (phoneNumberSet.contains(phoneNo) == false) {
							phoneNumberSet.add(phoneNo);
							int phoneType = pCur.getInt(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
							ContactItem contactItem = new ContactItem(phoneNo, name);
							contactItem.mType = phoneType;
							mAllContactItemList.add(contactItem);
						}
					}
					pCur.close();
				}
			}
		}	
		cur.close();
		return true;
	}
	
	
	public boolean sortAllContactItemList(Context context) {
		if (context == null) {
			return false;
		}
		mNormalContactItemList.clear();
		mAbnormalContactItemList.clear();
		for (int i = 0; i < mAllContactItemList.size(); i++) {
			ContactItem contactItem = mAllContactItemList.get(i);
			final String alphabet = "abcdefghijklmnopqrstuvwxyz";
			if (contactItem != null) {
				String name = contactItem.mContactName;
				String pinyin = PinyinUtil.toPinyin(context, name);
				if (pinyin == null || pinyin.equals("")) {
					contactItem.mPinyin = name;
				} else {
					contactItem.mPinyin = pinyin;
				}
				String temp = contactItem.mPinyin.substring(0, 1);
				if (alphabet.contains(temp)) {
					mNormalContactItemList.add(contactItem);
				} else {
					mAbnormalContactItemList.add(contactItem);
				}
			}
		}
		Collections.sort(mNormalContactItemList);
		Collections.sort(mAbnormalContactItemList);
		return true;
	}
	
	
	public final ArrayList<ContactItem> getNormalContactItemList() {
		return mNormalContactItemList;
	}
	
	public final ArrayList<ContactItem> getAbnormalContactItemList() {
		return mAbnormalContactItemList;
	}
	
	
	/**
	 * get all contacts
	 * @return ArrayList<ContactItem>
	 */
	public final ArrayList<ContactItem> getAllContactItemList() {
		return mAllContactItemList;
	}
}
